<?php
/**
 * Manager interface
 *
 * PHP version 5
 *
 * @category   Web
 * @package    Data2People
 * @subpackage Manager
 * @author     Mike Bevz <mike.bevz@data2people>
 * @copyright  2007-2008 (c) Mike Bevz
 * @license    The BSD License http://data2people.com/license.txt
 * @version    SVN: $Id:$
 *
 *
 */

require_once 'TV/Manager/Interface.php';
require_once 'Zend/Feed.php';

class TV_Manager_Feeds implements TV_Manager_Interface
{
    /**
     * Path to the file with feed URLs
     *
     * @var string
     */
    private $_config;

    public function __construct()
    {
        $this->_config = APP_PATH.DIRECTORY_SEPARATOR.'Config/feeds.xml';
    }
    /**
     * Updates all feeds
     *
     * @return boolean False if update is failed
     */
    public function update()
    {
        /**
         * 1. Get list of feeds
         * 2. For each feed run update process
         * 3. For each feed run tagging process
         * 4. For all feeds run tag cloud creation process
         *
         */
        $feeds = $this->getFeedList();
        
        foreach($feeds as $feed) {
            $this->updateFeed($feed);
        }
        
        $this->createCloud();
    }
    
    /**
     * Updates feed located at $url
     *
     * @param string $url
     */
    public function updateFeed($url)
    {
        if (!is_string($url)) {
            throw new TV_Manager_Exception(__METHOD__.' requires string as argument,
               got '.gettype($url));
        }
        try {
            $feed = Zend_Feed::import($url);
        } catch (Zend_Feed_Exception $e) {
            throw new TV_Manager_Exception($e->getMessage(), $e->getCode());
        }
        
        /*$channel = array(
            'title'       => $feed->title(),
            'link'        => $feed->link(),
            'description' => $feed->description(),
            'category'    => $feed->category(),
            'language'    => $feed->language(),
            'pubDate'     => $feed->pubDate(),
            'items'       => array()
        );*/

        $feeditem = new Feed();
        $feeds    = $feeditem->getByLink($feed->link());
        
        $pubdate = new Zend_Date($feed->pubDate());
        $pubdate = $pubdate->toString('Y-m-d H:i:s');
        $id      = '';
        if (count($feeds) == 1) {
            /**
             * Do not update if pubDate isn't changed
             */
            if ($feeds[0]->pubdate == $pubdate) {
                return;
            }
            
            $feeds[0]->title       = $feed->title();
            $feeds[0]->description = $feed->description();
            $feeds[0]->category    = $feed->category();
            $feeds[0]->language    = $feed->language();
            $feeds[0]->pubdate     = $pubdate;
            $feeds[0]->save();
            $feed_id = $feeds[0]->id;
        } else {
            $feeditem->title       = $feed->title();
            $feeditem->link        = $feed->link();
            $feeditem->description = $feed->description();
            $feeditem->category    = $feed->category();
            $feeditem->language    = $feed->language();
            $feeditem->pubdate     = $pubdate;
            $feeditem->save();
            $feed_id = $feeditem->id;
        }
        
        $this->tagItems($feed, $feed_id);
    }
    
    /**
     * Tags items of RSS feed with tags extracted from title and description
     *
     * @param Zend_Feed_Abstract $feed
     *
     * @return void
     */
    public function tagItems(Zend_Feed_Abstract $feed, $feed_id)
    {
        $termAnalyzer = new TV_Text_TermExtractor();
        
        foreach ($feed as $item) {
            $pubdate = new Zend_Date($item->pubDate());
            $pubdate = $pubdate->toString('Y-m-d H:i:s');
            
            $newsItem              = new News();
            $newsItem->title       = $item->title();
            $newsItem->link        = $item->link();
            $newsItem->pubdate     = $pubdate;
            $newsItem->description = $item->description();
            $newsItem->category    = $item->category();
            $newsItem->feed_id     = $feed_id;

            $tags = $termAnalyzer->getTags($item->description(), $item->title());
            foreach ($tags as $tag) {
                $newsItem->addTag($tag);
            }
            
            $ni   = new News();
            $news = $ni->getNewsByLink($item->link());
            if (count($news) == 0) {
               $newsItem->save();
            }
        }
        
    }
    
    public function createCloud()
    {
        /**
         * Number of elements in the cloud
         */
        $numElem = 400;
        
        $query = Doctrine_Query::create();
        $query->select('r.*, COUNT(r.news_id) count')
              ->from("TagRefNews r")
              ->orderBy('count DESC')
              ->groupBy('r.tag_id')
              ->limit($numElem);
              
        $tags = $query->execute();
        $max = 250;
        $min = 100;
        $occurMax = $tags[0]->count;
        $occurMin = $tags[$numElem-1]->count;
        $spread   = $occurMax - $occurMin;
        if (0 == $spread) {
            $spread = 1;
        }
        
        $step = ($max - $min) /($spread);
        
        $now      = Zend_Date::now();
        $now      = $now->toString('Y-m-d H:i:s');
        foreach($tags as $tag) {
            $cloud            = new Cloud();
            $cloud->content   = $tag->Tag->content;
            $cloud->occur     = $tag->count;
            $cloud->frequency = ceil($min + (($tag->count-$occurMin)*$step));
            $cloud->pubdate   = $now;
            $cloud->tag_id    = $tag->tag_id;
            $cloud->save();
        }
    }

    /**
     * Reads list of feeds from configuration file and returns array of their URLs
     *
     * @return array
     *
     */
    public function getFeedList()
    {
        $feeds = new Zend_Config_Xml($this->_config, 'feeds');

        $feedsURLs = array();
        foreach ($feeds->url as $feed) {
            $feedsURLs[] = $feed;
        }
        return $feedsURLs;
                                 
    }
    
    /**
     * Sets path to the configuration file
     *
     * @param string $path Path to the file
     */
    public function setConfig($path)
    {
        $this->_config = $path;
    }
    
    /**
     * Returns path to the configuration file
     *
     * @return string
     */
    public function getConfig()
    {
        return $this->_config;
    }
    
}